﻿using FluentParser.Expressions;
using FluentParser.Expressions.Rules.Composition;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FluentParser.Tests.Expressions.Rules.Composition
{
    [TestClass]
    public class SurroundSymbolRuleTests
    {
        [TestMethod]
        public void Parse_WhenParsingValidText_ShouldReturnTheCenterTokenValue()
        {
            SurroundSymbolRule surround = new SurroundSymbolRule("(", "text", ")");
            ParsingResult<object> result = surround.Parse("(text)");

            var expected = "text";
            var actual = result.Value;

            Assert.AreEqual(expected, actual);
            result.AssertLength("(text)");
        }

        [TestMethod]
        public void Parse_WhenParsingInvalidLeftToken_ShouldReturnNull()
        {
            SurroundSymbolRule surround = new SurroundSymbolRule("(", "text", ")");

            var expected = (ParsingResult<string>)null;
            var actual = surround.Parse("[text)");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Parse_WhenParsingInvalidCenterToken_ShouldReturnNull()
        {
            SurroundSymbolRule surround = new SurroundSymbolRule("(", "text", ")");

            var expected = (ParsingResult<string>)null;
            var actual = surround.Parse("(SomethingElse)");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Parse_WhenParsingInvalidRightToken_ShouldReturnNull()
        {
            SurroundSymbolRule surround = new SurroundSymbolRule("(", "text", ")");

            var expected = (ParsingResult<string>)null;
            var actual = surround.Parse("(text]");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void ParseNode_WhenParsingValidText_ShouldReturnTheCenterTokenValue()
        {
            SurroundSymbolRule surround = new SurroundSymbolRule("(", "text", ")");
            ParsingNodeResult node = surround.ParseNode("(text)");
            string expected = "text";
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            node.AssertLength("(text)");
            node.AssertExploredLength("(text)");

            node.AssertChildren(
                true, // "("
                true, // "text"
                true); // ")"
        }

        [TestMethod]
        public void ParseNode_WhenParsingInvalidLeftToken_ShouldReturnNull()
        {
            SurroundSymbolRule surround = new SurroundSymbolRule("(", "text", ")");
            ParsingNodeResult node = surround.ParseNode("[text)");

            string expected = null;
            string actual = node.Value as string;

            Assert.IsFalse(node.IsSuccess);
            Assert.AreEqual(expected, actual);
            node.AssertLength("");
            node.AssertExploredLength("?");

            node.AssertChildren(
                false); // "("
        }

        [TestMethod]
        public void ParseNode_WhenParsingInvalidCenterToken_ShouldReturnNull()
        {
            SurroundSymbolRule surround = new SurroundSymbolRule("(", "text", ")");
            ParsingNodeResult node = surround.ParseNode("(SomethingElse)");

            string expected = null;
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            node.AssertLength("");
            node.AssertExploredLength("(?");

            node.AssertChildren(
                true, // "("
                false); // "text"
        }

        [TestMethod]
        public void ParseNode_WhenParsingInvalidRightToken_ShouldReturnNull()
        {
            SurroundSymbolRule surround = new SurroundSymbolRule("(", "text", ")");
            ParsingNodeResult node = surround.ParseNode("(text]");

            string expected = null;
            string actual = node.Value as string;

            Assert.IsFalse(node.IsSuccess);
            Assert.AreEqual(expected, actual);
            node.AssertLength("");
            node.AssertExploredLength("(text?");

            node.AssertChildren(
                true, // "("
                true, // "text"
                false); // ")"
        }


    }
}
